package com.hefan.user.service;

import com.alibaba.fastjson.JSON;
import com.cat.common.constant.RedisKeyConstant;
import com.cat.common.entity.Page;
import com.cat.common.entity.ResultBean;
import com.cat.common.meta.ResultCode;
import com.cat.common.meta.UserTypeEnum;
import com.cat.common.meta.WebUserCachTypeEnum;
import com.cat.tiger.service.JedisService;
import com.cat.tiger.util.GlobalConstants;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.hefan.common.constant.InitUserConstants;
import com.hefan.common.exception.DataIllegalException;
import com.hefan.common.oss.OssImageService;
import com.hefan.common.util.DynamicProperties;
import com.hefan.common.util.MapUtils;
import com.hefan.user.bean.*;
import com.hefan.user.config.UserConfigCenter;
import com.hefan.user.dao.HfUserPreInitDao;
import com.hefan.user.dao.WebUserDao;
import com.hefan.user.itf.*;
import org.apache.commons.lang.StringUtils;
import org.slf4j.LoggerFactory;
import org.slf4j.profiler.Profiler;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by lxw on 2016/9/26.
 */
@Component("webUserService")
public class WebUserServiceImpl implements WebUserService {
    @Resource
    private WatchService watchService;
    @Resource
    private UserAuthService userAuthService;
    @Resource
    private UserSequenceService userSequenceService;
    @Resource
    private UserLevelService userLevelService;
    @Resource
    private UserCacheService userCacheService;
    @Resource
    private JedisService jedisService;

    @Resource
    private WebUserDao webUserDao;
    @Resource
    private UserConfigCenter userConfigCenter;
    @Resource
    WebUserService webUserService;

    @Resource
    private WatchCacheService watchCacheService;
    private static String PATH = DynamicProperties.getString("oss_static_path");
    private static String RANKINGLISTPATH = PATH + "RankingList.js";
    @Resource
    OssImageService ossImageService;
    @Resource
    private HfUserPreInitDao hfUserPreInitDao;
    @Resource
    private WebUserAccountService webUserAccountService;

    private org.slf4j.Logger logger = LoggerFactory.getLogger(WebUserServiceImpl.class);

    @Override
    @Transactional(readOnly=true)
    public int getWebUserCountByQueryVal(String queryVal, int paramType, int isDel) {
        int rowNum = webUserDao.getWebUserCountByQueryVal(queryVal,paramType,isDel);
        return rowNum;
    }

    @Override
    @Transactional(readOnly=true)
    public WebUser getWebUserInfoByIsDel(String userId,int isDel) {
        return webUserDao.getWebUserInfoByIsDel(userId,isDel);
    }

    @Override
    @Transactional(readOnly=true)
    public WebUser getWebUserInfoByUserId(String userId) {
        WebUser webUser = webUserDao.getWebUserBaseInfo(userId);
        userCacheService.getAllUserCach(webUser);
        return webUser;
    }

    @Override
    @Transactional(readOnly = true)
    public WebUser findUserInfoFromCache(String userId) {
        WebUser webUser = userCacheService.findUserInfoFromRedis(userId);
        if(webUser == null) {
            webUser = webUserDao.getWebUserBaseInfo(userId);
            userCacheService.setUserInfoToRedis(webUser);

        }
        return webUser;
    }

    @Override
    @Transactional(readOnly=true)
    public ResultBean getWebUserInfoByUserIdList(List userIdList) {
        List webUserList = webUserDao.getWebUserInfoByUserIdList(userIdList);
        if(webUserList == null || webUserList.isEmpty()) {
            webUserList = new ArrayList();
        }
        return new ResultBean(ResultCode.SUCCESS,webUserList);
    }

    @Override
    @Transactional(readOnly=true)
    public WebUser getWebUserInfoByThridParty(int type, String thridOpendId) {
        WebUser webUser = webUserDao.getWebUserInfoByUserIdList(type, thridOpendId);
        //获取用户累计缓存数据
        userCacheService.getAllUserCach(webUser);
        return webUser;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public WebUser saveRegisterUserInfo(WebUser webUser, int thridType, String account) {
        if(StringUtils.isBlank(webUser.getHeadImg())) {
            webUser.setHeadImg(DynamicProperties.getString("default.head.img"));
        }
        if(StringUtils.isBlank(webUser.getBackGround())) {
            webUser.setBackGround(DynamicProperties.getString("default.backGround.img"));
        }
        if(StringUtils.isBlank(webUser.getNickName())) {
            webUser.setNickName(webUser.getUserId());
        }
        WebUser webUser1 = null;
        if(thridType == 2 && StringUtils.isNotBlank(webUser.getUnionidWx())) {
            //微信登录先根据unionid检查用户是否存在
            webUser1 =  getWebUserInfoByThridParty(5,webUser.getUnionidWx());
        }
        if(webUser1 == null) {
            //检查用户信息是存在
            webUser1 = getWebUserInfoByThridParty(thridType,account);
        }
        if(webUser1 == null) {
            webUser = webUserDao.saveRegistWebUser(webUser);
            if (webUser != null) {
                //增加默认官方关注
                watchService.fork(webUser.getUserId(), InitUserConstants.OFFICE_USER_ID, GlobalConstants.OPRN_REMIND);
                //重新初始化用户递增缓存数据
                userCacheService.initAllUserCach(webUser);
            }
        } else {
            return webUser1;
        }
        return webUser;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ResultBean userAccountSafeOprate(String userId,int opFlag, int thirdType, String openid, String headImg, String nickName, String qq, String unionidWx) {
        List<Object> params = new ArrayList<Object>();
        //检查账户是否重复
        int eixstsCount = 0;
        if(opFlag == 1) { //绑定
            //检查新绑定信息是否存在
            if(thirdType == 2 && StringUtils.isNotBlank(unionidWx)) {
                eixstsCount = getWebUserCountByQueryVal(unionidWx, 5, 0);
            }
            if (eixstsCount == 0) {
                eixstsCount = getWebUserCountByQueryVal(openid, thirdType, 0);
            }
        }
        if(eixstsCount == 0 ) {
            params.add(openid);
            StringBuilder sqlBuilder = new StringBuilder();
            sqlBuilder.append("update web_user set ");
            switch (thirdType) {
                case 1 :  //微博openId查询
                    sqlBuilder.append(" openid_wb=? ");
                    break;
                case 2 : //微信openId查询
                    sqlBuilder.append(" openid_wx=? ");
                    sqlBuilder.append(" ,unionid_wx=? ");
                    params.add(StringUtils.isBlank(unionidWx)?"":unionidWx);
                    break;
                case 3 : //QQ的openId查询
                    sqlBuilder.append(" openid_qq=? ");
                    break;
                case 4 : //手机号查询
                    sqlBuilder.append(" mobile=? ");
                    break;
                default:
                    new ResultBean(ResultCode.AccountFial,null);
            }
            if(!StringUtils.isBlank(headImg)) {
                sqlBuilder.append(" ,head_img=? ");
                params.add(headImg);
            }
            if(!StringUtils.isBlank(nickName)) {
                sqlBuilder.append(" ,nick_name=? ");
                params.add(nickName);
            }
            sqlBuilder.append(" where user_id =? ");
            params.add(userId);
            int rowNum = webUserDao.update(sqlBuilder.toString(), params);
            if (rowNum > 0) {
                userCacheService.delUserBaseInfoCach(userId);
                return new ResultBean(ResultCode.SUCCESS, null);
            } else {
                return new ResultBean(ResultCode.AccountFial, null);
            }
        } else {
            return new ResultBean(ResultCode.AccountIsUsed, null);
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public int incrWebUserBalance(String userId, long incrBalance) {
        /*if(false) {
            //先不进行缓存优化
            WebUser webUser = webUserDao.getWebUserBaseInfo(userId);
            if(webUser != null && incrBalance != 0) {
                //累计饭票数
                Long cachBalance = userCacheService.incrUserCach(userId, WebUserCachTypeEnum.Balance_type,incrBalance);
                if(cachBalance == null) { //更新数据库 【增量更新】
                    webUserDao.updateUserBalanceDb(1,userId, incrBalance);
                } else {
                    if(WebUserCachTypeEnum.checkChangeBorderModifyToDb(WebUserCachTypeEnum.Balance_type,cachBalance,webUser.getBalance(),
                        MapUtils.getLongValue(userConfigCenter.getPublicConfig(),WebUserCachTypeEnum.Balance_type.getUpBorderZooKey(),
                                    WebUserCachTypeEnum.Balance_type.getUpBorder())
                    )) {
                        //饭票变化需要进行DB存储 【全量更新】
                        webUserDao.updateUserBalanceDb(2,userId, cachBalance.longValue());
                    }
                }
                if(incrBalance < 0) { //累计消费的贡献值
                    Long cachPayCount = userCacheService.incrUserCach(userId, WebUserCachTypeEnum.PayCount_type,Math.abs(incrBalance));
                    if(cachBalance == null) { //更新数据库 【增量更新】
                        webUserDao.updateUserPayCountDb(1,userId,Math.abs(incrBalance));
                    } else {
                        if(WebUserCachTypeEnum.checkChangeBorderModifyToDb(WebUserCachTypeEnum.PayCount_type,cachPayCount,webUser.getPayCount(),
                        MapUtils.getLongValue(userConfigCenter.getPublicConfig(),WebUserCachTypeEnum.PayCount_type.getUpBorderZooKey(),
                                    WebUserCachTypeEnum.PayCount_type.getUpBorder())
                        )) {
                            //饭票变化需要进行DB存储 【全量更新】
                            webUserDao.updateUserPayCountDb(2,userId, cachPayCount.longValue());
                        }
                    }
                }
                return 1;
            }
            return 0;
        }*/

        //直接进行DB更新
        String sql = "update web_user set balance=balance+? where user_id=?";
        Object[] params = new Object[]{incrBalance, userId};
        //如果饭票余额为负数，表示用户消费饭票增加用户贡献值和更新余额
        if (incrBalance < 0) {
            sql = "update web_user set pay_count=pay_count+?,balance=balance+? where user_id=? and balance+? >=0";
            params = new Object[]{incrBalance * -1, incrBalance, userId, incrBalance};
        }
        int rowNum = webUserDao.update(sql, params);
        if (rowNum <= 0) {
            logger.error("incrWebUserBalance--fail--uid:{}--balance:{incrBalance}", userId, incrBalance);
        }
        return rowNum;
    }

    public int incrWebUserBalanceAndHefan(String userId, long incrBalance, long hefanNum) {
        //减少普通用户盒饭数
        int rowNum = webUserAccountService.updateOrInsertForBaseUserIncome(userId, hefanNum);
        if (rowNum > 0) {
            String sql = "update web_user set balance=balance+? where user_id=? ";
            Object[] params = new Object[]{incrBalance, userId};
            rowNum = webUserDao.update(sql, params);
            if (rowNum > 0) {
                userCacheService.delUserBaseInfoCach(userId);
            }
        }
        return rowNum;
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
    public int icrWebUserHefanTotal(String userId, long hefanVal) {
        Profiler profiler = new Profiler("icrWebUserHefanTotal--start");
        //if(false) { //先不进行缓存优化
        WebUser webUser = webUserDao.getWebUserBaseInfo(userId);
        if (webUser != null) {
            //非主播的用户的收入记录到web_user_ordinary_income
            if (!UserTypeEnum.isAnchor(webUser.getUserType())) {
                int count = webUserAccountService.updateOrInsertForBaseUserIncome(userId, hefanVal);
                if (count <= 0) {
                    throw new DataIllegalException("普通用户收入记录异常！userId=" + userId);
                }
            }
            Long cachHefanTaotal = userCacheService.incrUserCach(userId, WebUserCachTypeEnum.HefanTotal_type, hefanVal);
            boolean isModifyDb = false; //是否需要变更
            int userLevel = 0;
            int incrMode;
            long modifyVal;
            if (cachHefanTaotal == null) { //未进行缓存更新 需要进行DB更新
                incrMode = 1; //更新方式累计更新
                isModifyDb = true;
                modifyVal = hefanVal;
                cachHefanTaotal = webUser.getHefanTotal().longValue() + hefanVal;
            } else { //cach更新完毕，验证是否进行DB更新

                isModifyDb = WebUserCachTypeEnum.checkChangeBorderModifyToDb(WebUserCachTypeEnum.HefanTotal_type,
                        cachHefanTaotal, webUser.getHefanTotal(),
                        MapUtils.getLongValue(userConfigCenter.getPublicConfig(), WebUserCachTypeEnum.HefanTotal_type.getUpBorderZooKey(),
                                WebUserCachTypeEnum.HefanTotal_type.getUpBorder()));
                incrMode = 2; //更新方式全量更新
                modifyVal = cachHefanTaotal.longValue();
            }
            if (UserTypeEnum.isRedAnchor(webUser.getUserType())) { //网红计算等级
                WebUserNetworkStirLevel webUserNetworkStirLevel = userLevelService.networkStirLevelCalc(cachHefanTaotal.longValue());
                userLevel = webUser.getUserLevel();
                if (webUserNetworkStirLevel != null) {
                    userLevel = webUserNetworkStirLevel.getLevelVal();
                    if (isModifyDb || webUser.getUserLevel() != userLevel) { //是否存在等级变化
                        isModifyDb = true;
                    }
                }
            }
            if (isModifyDb) { //需要进行DB更新
                int rowNum = webUserDao.updateUserHefanTotalDb(incrMode, userId, modifyVal, userLevel);
                if (rowNum > 0) {
                    webUser.setUserLevel(userLevel);
                    userCacheService.setUserInfoToRedis(webUser);
                }
            }
            return 1;
        }
        return 0;
        //}
        //直接进行DB更新
        /*int rest = 1;
        profiler.start("icrWebUserHefanTotal--getWebUserBaseInfo--runTime@@");
        WebUser webUser = webUserDao.getWebUserBaseInfo(userId);
        if(webUser != null) {
            int userLevel =0;
            if(UserTypeEnum.isRedAnchor(webUser.getUserType())) { //网红计算等级
                profiler.start("icrWebUserHefanTotal--networkStirLevelCalc--runTime@@");
                WebUserNetworkStirLevel webUserNetworkStirLevel = userLevelService.networkStirLevelCalc(webUser.getHefanTotal()+hefanVal);
                if(webUserNetworkStirLevel != null) {
                    userLevel = webUserNetworkStirLevel.getLevelVal();
                }
            }
            if(!(UserTypeEnum.isAnchor(webUser.getUserType()))){
                logger.info("icrWebUserHefanTotal--非主播用户--userId:{}",webUser.getUserId());
                rest = 0;
            } else {
                profiler.start("icrWebUserHefanTotal--updateUserHefanTotalDb--runTime@@");
                rest = webUserDao.updateUserHefanTotalDb(1,userId, hefanVal, userLevel);
                logger.info("icrWebUserHefanTotal--userId:{}--hefanTotal:{}--userLevel:{}--result:{}",webUser.getUserId(),hefanVal,userLevel,rest);
            }
        } else {
            rest = 0;
            logger.info("icrWebUserHefanTotal--用户不存在");
        }
        profiler.stop().print();
        return rest;*/
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
    public void incrWebUserHefanFromCach(String userId) {
        WebUser webUser = this.findUserInfoFromCache(userId);
        Long hefanTotal = userCacheService.getIncrUserCach(userId, WebUserCachTypeEnum.HefanTotal_type);
        if (hefanTotal != null && webUser != null) {
            int userLevel = webUser.getUserLevel();
            if (UserTypeEnum.isRedAnchor(webUser.getUserType())) { //网红计算等级
                WebUserNetworkStirLevel webUserNetworkStirLevel = userLevelService.networkStirLevelCalc(hefanTotal.longValue());
                if (webUserNetworkStirLevel != null) {
                    userLevel = webUserNetworkStirLevel.getLevelVal();
                }
            }
            int rowNum = webUserDao.updateUserHefanTotalDb(2, userId, hefanTotal.longValue(), userLevel);
            if (rowNum > 0) {
                webUser.setUserLevel(userLevel);
                userCacheService.setUserInfoToRedis(webUser);
            }
        }
    }


    @Override
    @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
    public ResultBean updateWebUserBaseInfo(WebUser webUser) {
        int updateRow = webUserDao.updateWebUserBaseInfo(webUser);
        if (updateRow > 0) {
            userCacheService.delUserBaseInfoCach(webUser.getUserId());
        }
        return new ResultBean(ResultCode.SUCCESS, null);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public int updateWebUserIdentityStatus(String userId, int identityStatus) {
        String sql = "update web_user set identity_status=? where user_id=?";
        int rowNum = webUserDao.update(sql, new Object[]{identityStatus, userId});
        if (rowNum > 0) {
            userCacheService.delUserBaseInfoCach(userId);
        }
        return rowNum;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public int updateWebUserLocation(String userId, String gpsLocation) {
        String sql = "update web_user set gps_location=? where user_id=?";
        int rowNum = webUserDao.update(sql, new Object[]{gpsLocation, userId});
        if (rowNum > 0) {
            userCacheService.delUserBaseInfoCach(userId);
        }
        return rowNum;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public int updateWebUserLiveInfo(String userId, String liveUuid, String token) {
        String sql = "update web_user set live_uuid=?,token=? where user_id=?";
        int rowNum = webUserDao.update(sql, new Object[]{liveUuid, token, userId});
        if (rowNum > 0) {
            userCacheService.delUserBaseInfoCach(userId);
        }
        return rowNum;
    }

    @Override
    @Transactional(readOnly = true)
    public WebUser findMyUserInfo(String userId) {
        WebUser webUser = this.getWebUserInfoByUserId(userId);
        if (webUser != null) {
            //修改：2017-03-29 王超 不区分主播和普通用户，都显示粉丝和盒饭数（web_user表hefan_total）
/*            //是否为主播
            if (UserTypeEnum.isAnchor(webUser.getUserType())) {
                //获取粉丝数
                long fansCount = watchService.findFansCount(userId);
                webUser.setFansCount(fansCount);
            } else {
                //获取收入盒饭数（普通用户）
                long income = webUserAccountService.getBaseUserIncome(userId);
                webUser.setHefanTotal(income);
            }*/
            long fansCount = watchService.findFansCount(userId);
            webUser.setFansCount(fansCount);
            //获取关注数
            long watcherCount = watchService.findWatchedCount(userId);
            webUser.setWatcherCount(watcherCount);
            //获取官方认证信息
            String authInfo = userAuthService.findAnchorInfo(webUser);
            webUser.setAuthInfo(authInfo);
        }
        return webUser;
    }

    @Override
    @Transactional(readOnly = true)
    public WebUser findMyUserInfoFromCach(String userId) {
        WebUser webUser = this.findUserInfoFromCache(userId);
        if (webUser != null) {
            //是否为主播
            if (UserTypeEnum.isAnchor(webUser.getUserType())) {
                //获取粉丝数
                long fansCount = watchService.findFansCount(userId);
                webUser.setFansCount(fansCount);
            }
            //获取关注数
            long watcherCount = watchService.findWatchedCount(userId);
            webUser.setWatcherCount(watcherCount);
            //获取官方认证信息
            String authInfo = userAuthService.findAnchorInfo(webUser);
            webUser.setAuthInfo(authInfo);
        }
        return webUser;
    }

    @Override
    @Transactional(readOnly = true)
    public WebUser findOtherUserInfo(String userId, String beViUserId) {
        //被查看人的用户基本信息
        WebUser beViWebUser = findMyUserInfo(beViUserId);
        //不为本人看本人、被查看用户信息非空
        if (!userId.equals(beViUserId) && beViWebUser != null) {
            //是否被关在状态
            //int isWatched = watchService.isWatchedCheck(userId, beViUserId);
            int isWatched = watchCacheService.getWatchRelationByUserId(userId, beViUserId);
            //0:已关注 1:互粉 2：没关系
            if (isWatched == 0 || isWatched == 1) {
                isWatched = 1;
            } else {
                isWatched = 0;
            }
            beViWebUser.setIsWatched(isWatched);

        }
        return beViWebUser;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ResultBean userLevelOprate(String userId, long incrExp) {
        WebUser webUser = webUserDao.getWebUserBaseInfo(userId);
        if (webUser == null) {
            return new ResultBean(ResultCode.UNSUCCESS, null);
        }
        //组装用户等级变更VO
        UserLevelChangeVo userLevelChangeVo = new UserLevelChangeVo();
        userLevelChangeVo.setUserId(userId);
        userLevelChangeVo.setIsChange(0);
        if (!UserTypeEnum.isAnchor(webUser.getUserType())) { //非明星|片场|网红计算经验和等级
            Long cachExp = userCacheService.incrUserCach(userId, WebUserCachTypeEnum.Exp_type, incrExp);
            boolean isModifyDb = false; //是否需要变更
            int userLevel = 0;
            int incrMode;
            long modifyVal;
            if (cachExp == null) {
                incrMode = 1; //更新方式累计更新
                isModifyDb = true;
                modifyVal = incrExp;
                cachExp = webUser.getExp().longValue() + incrExp;
            } else {
                isModifyDb = WebUserCachTypeEnum.checkChangeBorderModifyToDb(WebUserCachTypeEnum.Exp_type, cachExp.longValue(),
                        webUser.getExp().longValue(),
                        MapUtils.getLongValue(userConfigCenter.getPublicConfig(), WebUserCachTypeEnum.Exp_type.getUpBorderZooKey(),
                                WebUserCachTypeEnum.Exp_type.getUpBorder())
                );
                incrMode = 2; //更新方式全量更新
                modifyVal = cachExp.longValue();
            }
            //根据经验计算用户等级
            WebUserLevel webUserLevel = userLevelService.userLevelCalc(cachExp);
            int changeLevel = webUser.getUserLevel();
            if (webUserLevel != null) {
                changeLevel = webUserLevel.getLevelVal();
            }
            if (changeLevel > webUser.getUserLevel()) {
                userLevelChangeVo.setIsChange(1);
            }
            if (isModifyDb || userLevelChangeVo.getIsChange() == 1) { //需要进行DB更新
                int rowNum = webUserDao.updateUserExpDb(incrMode, userId, modifyVal, changeLevel);
                if (rowNum > 0) {
                    webUser.setUserLevel(userLevel);
                    userCacheService.setUserInfoToRedis(webUser);
                }
            }
            userLevelChangeVo.setUserLevel(changeLevel);
            userLevelChangeVo.setExp(cachExp);
        }
        return new ResultBean(ResultCode.SUCCESS, userLevelChangeVo);
    }

    @Override
    public List recommendAnchorFirst(String userId) {
        StringBuilder sql = new StringBuilder();
        sql.append(" SELECT ");
        sql.append(" wu.user_id id, ");
        sql.append(" wu.nick_name name, ");
        sql.append(" wu.user_type type, ");
        sql.append(" wu.head_img headImg ");
        sql.append(" FROM web_user wu  ");
        sql.append(" WHERE ");
        sql.append(" wu.user_type IN(2,3) ");
        sql.append(" AND wu.superior_contract_state = 0  ");
        sql.append(" AND wu.state  = 0 ");
        sql.append(" AND wu.contract_state = 0 ");
        sql.append(" AND wu.superior_state = 0 ");
        sql.append(" AND wu.is_del = 0 ");
        sql.append(" AND wu.user_id !=100000001 ");
        sql.append(" ORDER BY RAND()  LIMIT 27 ");
        List<Map<String, Object>> listMap = webUserDao.queryMap(sql.toString());
        for (Map map : listMap) {
            //新关注关系 0关注1互粉2未关注
            map.put("isFollow", watchCacheService.getWatchRelationByUserId(userId, String.valueOf(map.get("id"))));
        }
        return listMap;
    }

    @Override
    public Page getAnchorRankingList(Page page, String userId, int type) throws Exception {

        Page pageData = userCacheService.getAnchorRankingList(type, page);
        List<Map<String, String>> listData = pageData.getResult();

        logger.info("主播{}排行榜,缓存获取数据page={},list={}", type == 0 ? "积分" : "实力", page.getPageNo(), listData);
        if (CollectionUtils.isEmpty(listData)) {
            logger.info("主播{}排行榜缓存数据为空,从数据库获取");
            //缓存数据为空，从数据库获取
            getUserRankingData("", type);
            pageData = userCacheService.getAnchorRankingList(type, page);
        }
        //出发积分榜时，更新静态文件
        if (type == 0) {
            logger.info("积分榜缓存同步静态文件");
            syncOSS();
        }
        return pageData;

    }

    private void dealOtherUserForRanking(List<WebUser> list, List<Map<String, Object>> innerUserList, List<Map<String, Object>> blackUserList, int type, long multiple) throws Exception {
        for (WebUser webUser : list) {
            if (type != 1) {
                if (!CollectionUtils.isEmpty(innerUserList)) {
                    for (Map<String, Object> temp : innerUserList) {
                        Long hefanTotal = webUser.getHefanTotal();
                        if (webUser.getUserId().equals(temp.get("userId"))) {
                            //扣除内部用户
                            webUser.setHefanTotal(hefanTotal - Long.parseLong(temp.get("total").toString()));
                            break;
                        }
                    }
                }
                if (!CollectionUtils.isEmpty(blackUserList)) {
                    for (Map<String, Object> temp : blackUserList) {
                        Long hefanTotal = webUser.getHefanTotal();
                        if (webUser.getUserId().equals(temp.get("userId"))) {
                            //扣黑名单
                            webUser.setHefanTotal(hefanTotal - Long.parseLong(temp.get("total").toString()));
                            break;
                        }
                    }
                }
            }
            Map<String, String> stringMap = Maps.newHashMap();
            stringMap.put("userId", webUser.getUserId());
            stringMap.put("authName", userAuthService.findAnchorInfo(webUser));
            long total = webUser.getHefanTotal();
            if (total > 0) {
                //0(实力榜)总榜，1收入榜,2月榜
                if (type == 1) {
                    stringMap.put("ticketHistory", String.valueOf(total));
                } else {
                    stringMap.put("ticketHistory", String.valueOf(total * multiple));
                }
                stringMap.put("nickName", webUser.getNickName());
                stringMap.put("userType", String.valueOf(webUser.getUserType()));
                stringMap.put("authId", String.valueOf(webUser.getAuthId()));
                stringMap.put("sex", String.valueOf(webUser.getSex()));
                stringMap.put("headImg", webUser.getHeadImg());
                logger.info("排行榜缓存数据{}", stringMap);
                userCacheService.cacheAnchorRanking(type, stringMap);
            }
        }
    }


    /**
     * 主播排行榜新需求
     *
     * @param page
     * @param type 0:总榜，2月榜
     * @return
     * @throws Exception
     */
    @Override
    public Page getAnchorRankingList2(Page page, int type) throws Exception {
        //如果请求的是总榜调用之前的方法
        if (0 == type) {
            return getAnchorRankingList(page, "", type);
        }
        Page pageData = userCacheService.getAnchorRankingList(type, page);
        List<Map<String, String>> listData = pageData.getResult();
        logger.info("主播{}排行榜,缓存获取数据page={},list={}", type == 2 ? "月榜" : "总榜page.getPageNo(), listData");
        //缓存数据为空，从数据库获取
        if (CollectionUtils.isEmpty(listData)) {
            logger.info("主播{}排行榜缓存数据为空,从数据库获取");
            //积分排行榜获取所有黑名单，并统计黑名单赠送的饭票数
            getUserMonthRankingData("");
            pageData = userCacheService.getAnchorRankingList(type, page);
        }

        return pageData;
    }

    /**
     * 同步发现页主播排行榜（5条数据）
     *
     * @return
     * @throws
     * @author wangchao
     * @create 2016/12/13 11:03
     */
    @Override
    public void syncOSS() {
        ResultBean resultBean = new ResultBean();
        try {
            Page page = new Page();
            page.setPageNo(1);
            page.setPageSize(5);
            Page<Map<String, Object>> pageData = userCacheService.getAnchorRankingList(0, page);
            if (pageData == null || CollectionUtils.isEmpty(pageData.getResult())) {
                logger.error("WebUserServiceImpl主播排行榜查询空");
                return;
            }
            List<Map<String, Object>> list = pageData.getResult();
            List<Map<String, Object>> listData = Lists.newArrayList();
            for (Map<String, Object> map : list) {
                Map<String, Object> temp = Maps.newHashMap();
                temp.put("id", map.get("userId"));
                temp.put("name", map.get("nickName"));
                temp.put("type", map.get("userType"));
                temp.put("headImg", map.get("headImg"));
                listData.add(temp);
            }
            resultBean.setData(listData);
            resultBean.setCode(ResultCode.SUCCESS.get_code());
            ByteArrayInputStream buf = new ByteArrayInputStream(JSON.toJSONString(resultBean).getBytes("utf-8"));
            ossImageService.updataFile(GlobalConstants.PIC_OSS_BUCKET, buf, buf.available(), RANKINGLISTPATH);
            logger.info("主播排行榜文件SUCCESS");
        } catch (Exception e) {
            logger.error("主播排行榜查询出错");
            e.printStackTrace();
        }
    }

    /**
     * mgmt 后台手动刷新排行榜
     *
     * @return
     * @throws Exception
     * @description 仅用于后台手动刷新
     * @author wangchao
     * @create 2017/2/8 14:24
     */
    @Override
    public void refreshRanking() throws Exception {
        try {
            String key = RedisKeyConstant.ANCHOR__RANKING_LIST + RedisKeyConstant.KEY_ACTIVE_LIST;
            //新增获取月榜的redisKey
            //刷新主播总榜
            jedisService.del(key);
            getUserRankingData("", 0);
        } catch (Exception e) {
            logger.error("刷新主播总榜异常", e);
        }
        try {
            String key = RedisKeyConstant.ANCHOR__HF_RANKING_LIST_EVERYMONTH + RedisKeyConstant.KEY_ACTIVE_LIST;
            jedisService.del(key);
            //刷新主播月榜
            getUserMonthRankingData("");
        } catch (Exception e) {
            logger.error("刷新主播月榜异常", e);
        }
    }

    @Override
    public void getUserMonthRankingData(String userId) throws Exception {

        Map<String, String> map = userConfigCenter.getPublicConfig();
        String blackList = StringUtils.isBlank(map.get("rankBlackList")) ? "" : map.get("rankBlackList");
        long multiple = StringUtils.isBlank(map.get("multiple")) ? 10 : Long.parseLong(map.get("multiple"));
        logger.info("黑名单{},积分倍数{}", blackList, multiple);
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT  wu.user_id, wu.nick_name, wu.auth_id, wu.sex,sum(wui.hefan_num) hefan_total, wu.head_img,wu.user_type,wu.user_level ");
        sql.append("FROM web_user_income wui, web_user wu ");
        sql.append("WHERE  wui.user_id = wu.user_id AND wui.source in(0,1)");
        if (StringUtils.isNotBlank(blackList)) {
            sql.append(" AND wui.from_user_id not in (:ids) ");
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();//获取开始时间
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), 1, 0, 0, 0);
        String starTime = sdf.format(calendar.getTime());
        Calendar cal_end = Calendar.getInstance();//获取结束时间
        cal_end.set(cal_end.get(Calendar.YEAR), cal_end.get(Calendar.MONTH), cal_end.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
        String endTime = sdf.format(cal_end.getTime());
        sql.append(" AND wui.create_time between '").append(starTime).append("' and '").append(endTime)
                .append("'AND wu.superior_contract_state = 0 AND wu.state  = 0 AND wu.contract_state = 0  AND wu.superior_state = 0");
        if (StringUtils.isNotBlank(userId)) {
            sql.append(" AND  wui.user_id=").append(userId);
        }
        sql.append(" AND wu.is_del = 0  AND wu.user_type = 1 GROUP BY wui.user_id;");
        List<WebUser> list;
        if (StringUtils.isNotBlank(blackList)) {
            list = webUserDao.getEntityList2(sql.toString(), "ids", new HashSet(Arrays.asList(blackList.split(","))));
        } else {
            list = webUserDao.query(sql.toString(), null, WebUser.class);
        }
        if (!CollectionUtils.isEmpty(list)) {
            //查询所有内部用户送的
            List<Map<String, Object>> innerUserList = webUserDao.queryMap(
                    "select sum(wui.hefan_num) total,wui.user_id userId from web_user_income wui,web_user wu where wui.from_user_id=wu.user_id and wui.source in(0,1) and  wu.user_type=4 and wui.create_time between ? and ? GROUP BY wui.user_id",
                    new Object[]{starTime, endTime});
            logger.info("月榜处理内部、黑名单用户");
            dealOtherUserForRanking(list, innerUserList, null, 2, multiple);
        }
    }

    @Override
    public void getUserRankingData(String userId, int type) throws Exception {
        //主播排行榜
        StringBuilder sql = new StringBuilder();
        //积分排行榜获取所有黑名单，并统计黑名单赠送的饭票数
        Map<String, String> map = userConfigCenter.getPublicConfig();
        String blackList = StringUtils.isBlank(map.get("rankBlackList")) ? "" : map.get("rankBlackList");
        long multiple = StringUtils.isBlank(map.get("multiple")) ? 10 : Long.parseLong(map.get("multiple"));
        logger.info("黑名单{},积分倍数{}", blackList, multiple);
        Page<WebUser> userPage = new Page<>();
        userPage.setPageNo(1);
        userPage.setPageSize(1000000);
        sql.append(" SELECT  wu.user_id, wu.nick_name,  wu.auth_id, wu.sex, wu.hefan_total, wu.head_img,wu.user_type,wu.user_level FROM web_user wu  ");
        sql.append(" WHERE  wu.superior_contract_state = 0   AND wu.state  = 0  AND wu.contract_state = 0  AND wu.superior_state = 0 ")
                .append(" AND wu.is_del = 0  AND wu.user_type = 1  AND wu.hefan_total != 0 ");
        userPage = webUserDao.findPage(userPage, sql.toString(), null, WebUser.class);
        List<WebUser> list = userPage.getResult();

        if (!CollectionUtils.isEmpty(list)) {
            List<Map<String, Object>> innerUserList = null;
            List<Map<String, Object>> blackUserList = null;
            if (type == 0) {
                //查询所有内部用户送的
                innerUserList = webUserDao
                        .queryMap("select sum(wui.hefan_num) total,wui.user_id userId from web_user_income wui,web_user wu where wui.from_user_id=wu.user_id and wui.source in(0,1) and  wu.user_type=4 GROUP BY wui.user_id");
                //查询所有黑名单
                if (StringUtils.isNotBlank(blackList)) {
                    blackUserList = webUserDao
                            .getEntityList("select sum(wui.hefan_num) total,wui.user_id userId from web_user_income wui where  wui.source in(0,1) and wui.from_user_id in (:ids) GROUP BY wui.user_id", "ids",
                                    new HashSet(Arrays.asList(blackList.split(","))));
                }
            }
            logger.info("黑名单{}", blackUserList);
            dealOtherUserForRanking(list, innerUserList, blackUserList, type, multiple);
        }
    }

    @Override
    public Page recommendStarClub(Page page, String userId) {
        StringBuilder sql = new StringBuilder();
        sql.append(" SELECT ");
        sql.append(" wu.user_id id, ");
        sql.append(" wu.person_sign personSign, ");
        sql.append(" wu.nick_name name, ");
        sql.append(" wu.user_type type, ");
        sql.append(" wu.head_img headImg, ");
        sql.append(" (SELECT COUNT(1) FROM watch_relation wr WHERE wr.user_id = ? AND main_user_id = wu.user_id) isWatched ");
        sql.append(" FROM web_user wu  ");
        sql.append(" WHERE ");
        sql.append(" wu.superior_contract_state = 0  ");
        sql.append(" AND wu.state  = 0 ");
        sql.append(" AND wu.user_id != ? ");
        sql.append(" AND wu.contract_state = 0 ");
        sql.append(" AND wu.superior_state = 0 ");
        //sql.append(" AND wu.is_del = 0 ");
        sql.append(" AND wu.user_type IN (2,3) ");
        Page pageList = webUserDao.findPageMap(page, sql.toString(), userId, userId);
        List<Map<String, Object>> listMap = pageList.getResult();
        for (Map key : listMap) {
            key.put("watchedCount", watchService.findWatchedCount(key.get("id").toString()));
            key.put("fansCount", watchService.findAllFansCount(key.get("id").toString()));
            //新关注关系 0关注1互粉2未关注
            key.put("isFollow", watchCacheService.getWatchRelationByUserId(userId, String.valueOf(key.get("id"))));
        }
        pageList.setResult(listMap);
        return pageList;
    }

    /**
     * 更新用户观看时长
     *
     * @param userId
     * @param watchTime
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public int updateUserWatchTime(String userId, long watchTime) {
        String sql = "update web_user set watch_total_time=watch_total_time+? where user_id=?";
        return webUserDao.update(sql, new Object[]{watchTime, userId});
    }

    @Override
    public List<Map<String, Object>> getPunishDetail() {
        // TODO Auto-generated method stub
        String sql = "select a.user_id,b.nick_name,a.category,a.type_name,a.live_uuid,"
                + " a.punish_reason,a.illegal_pic,a.from_type,a.freeze_days,a.stop_days,"
                + " a.ded_money,a.ded_commision,a.cancel_flag,a.cancel_reason,a.cancel_user,"
                + " DATE_FORMAT(a.cancel_time,'%Y-%m-%d %H:%i:%s') cancelTime,"
                + " DATE_FORMAT(a.create_time,'%Y-%m-%d %H:%i:%s') createTime,a.create_user"
                + " from punish_detail a LEFT JOIN web_user b"
                + " on a.user_id=b.user_id  order by a.create_time desc";
        return webUserDao.queryMap(sql.toString());
    }

    @Override
    public Page<WebUser> getWebListByPage(Page<WebUser> page) {
        return webUserDao.findPage(page, "SELECT user_id FROM web_user WHERE is_del = 0 and state=1", new Object[]{}, WebUser.class);
    }

    @Override
    public WebUser getDynaUser(String userId) {
        WebUser webUser = webUserService.findUserInfoFromCache(userId);
        if (null != webUser && UserTypeEnum.isAnchor(webUser.getUserType())) {
            logger.info("查询的用户为主播用户");
            return webUserDao.getDynaUser(userId);
        } else {
            logger.info("查询的用户为普通用户");
            return webUserDao.getDynaNormalUser(userId);
        }
    }

    @Override
    @Transactional(readOnly = true)
    public int modifyWebUserInfoNewWxOpenId(String userId, String wxOpenId) {
        int rowNum = this.getWebUserCountByQueryVal(wxOpenId, 2, 0);
        if (rowNum > 0) { //已经存在openId信息
            return 0;
        } else {
            webUserDao.modifyNewWxOpenId(userId, wxOpenId);
        }
        return 1;
    }

    @Override
    @Transactional(readOnly = true)
    public HfUserPreInit getUserPreInit(String userId) {
        return hfUserPreInitDao.queryUserPreInitInfo(userId);
    }

    /**
     * 扣费（（直播间/俱乐部）礼物，红包）成功后更新主播排行榜，总榜，月榜
     * 如果送礼人是内部用户或黑名单则不更新榜单
     * 影响扣费性能 废弃
     *
     * @param fromId
     * @param authId   主播id
     * @param hefanNum 增长的盒饭数
     * @return
     * @throws
     * @author wangchao
     * @create 2017/2/7 11:51
     */
    @Override
    @Deprecated
    public void updateRankByRebalance(String fromId, String authId, int hefanNum) throws Exception {
        userCacheService.updateRankByRebalance(fromId, authId, hefanNum);
    }

    @Override
    @Transactional(readOnly = true)
    public List<WebUser> findInvalidUserInfoByUpdateTime(String updateTimeStr) throws Exception {
        return webUserDao.findInvalidUserInfoByUpdateTime(updateTimeStr);
    }

    /**
     * 更新用户的unionidWx
     * @param userId
     * @param unionidWx
     * @throws Exception
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateWebUserUnionidWx(String userId, String unionidWx) throws Exception {
        webUserDao.updateWebUserUnionidWx(userId,unionidWx);
    }

}
